import { WeilaCore, WL_MsgData, WL_SessionType, WL_MsgDataType, WL_LocationData, WL_MediaData } from "weilasdk_lite";
import { uploadFile } from "../../../utils/apis";
import LongModule from 'long';
const Long = LongModule.default || LongModule;

// Define an enum for message types using numbers
enum MessageType {
  TEXT = 0,
  VOICE = 1,
  IMAGE = 2,
  VIDEO = 3,
  LOCATION = 4,
  FILE = 5
}

interface Message {
  msgId: number;
  created: number;
  isSelf: boolean;
  name: string;
  avatar: string;
  type: MessageType; // Use the numeric enum here
  content?: string | null;
  size?: number | null;
  timestamp: string;
  duration?: number | string | null;
  thumbnail?: string | null;
  mapImage?: string | null;
  latitude?: number | null;
  longitude?: number | null;
  title?: string | null;
  address?: string | null;
  state: 'sending' | 'done' | 'failed';
}

interface AttachmentItem {
  type: MessageType;
  name: string;
  icon: string;
}

type RecordingState = 'idle' | 'recording' | 'will-cancel';

// 录音管理器实例
const recorderManager = wx.getRecorderManager();

Page({
  data: {
    messages: [] as Message[],
    msgDatas: [] as WL_MsgData[],
    sessionId: '',
    inputMessage: '',
    isVoiceMode: false,
    showAttachmentMenu: false,
    isAtBottom: true,
    scrollTop: 0,
    isRefreshing: false,
    recordingState: 'idle' as RecordingState,
    recordingTime: 0,
    recordingTimer: null as any,
    touchStartY: 0,
    lastMessageHeight: 0,
    previousScrollPosition: 0,
    totalMessagesHeight: 0,
    safeAreaBottom: 0,
    loginUserInfo: null as any,
    attachmentItems: [
      { type: MessageType.IMAGE, name: '图片', icon: 'fas fa-image' },
      { type: MessageType.VIDEO, name: '视频', icon: 'fas fa-video-camera' },
      { type: MessageType.LOCATION, name: '位置', icon: 'fas fa-map' },
    ] as AttachmentItem[]
  },

    /**
   * Format timestamp from UTC seconds to local time.
   */
  formatTimestamp(utcSeconds: number): string {
    return new Date(utcSeconds * 1000).toLocaleTimeString('zh-CN', {
    hour: 'numeric',
    minute: 'numeric',
    hour12: true
    });
  },

  // get user name and avatar from userid
  getUserInfoFromUserId(userId: number): { name: string; avatar: string } {

    return {
      name: '微喇客服',
      avatar: '/assets/image/logo.png'
    };
  },

  transformToWeChatMessages(messages: WL_MsgData[]): Message[] {
    let loginUser = this.data.loginUserInfo;

    console.log("messages", messages);
  

    return messages.map((msg) => {
      const isSelf = msg.senderId === loginUser.userId!;
      console.log("msg created is: ", typeof msg.created, msg.created);
      
      const timestamp = this.formatTimestamp(msg.created!);
      const { name, avatar } = this.getUserInfoFromUserId(msg.senderId!);

      switch (msg.msgType!) {
        case WL_MsgDataType.WL_MSG_DATA_TEXT_TYPE:
          return {
            msgId: msg.msgId!,
            created: msg.created!,
            isSelf,
            name: name,
            avatar: avatar,
            type: MessageType.TEXT,
            content: msg.textData,
            timestamp,
            state: 'done'
          };
        case WL_MsgDataType.WL_MSG_DATA_AUDIO_TYPE:

          // the audio url is like http://businessaudio.oss-cn-shenzhen.aliyuncs.com/…050809163/2025514/1253650_1747210541_3?duration=3
          // get duration from url
          const duration = msg.audioData?.url?.match(/duration=(\d+)/);

          return {
            msgId: msg.msgId!,
            created: msg.created!,
            isSelf,
            name: name,
            avatar: avatar,
            type: MessageType.VOICE,
            content: msg.audioData?.url,
            duration: duration ? duration[1] : 0,
            timestamp,
            state: 'done'
          };
        case WL_MsgDataType.WL_MSG_DATA_IMAGE_TYPE:
          return {
            msgId: msg.msgId!,
            created: msg.created!,
            isSelf,
            name: name,
            avatar: avatar,
            type: MessageType.IMAGE,
            content: msg.fileInfo?.url,
            timestamp,
            state: 'done'
          };
        case WL_MsgDataType.WL_MSG_DATA_VIDEO_TYPE:
          return {
            msgId: msg.msgId!,
            created: msg.created!,
            isSelf,
            name: name,
            avatar: avatar,
            type: MessageType.VIDEO,
            content: msg.fileInfo?.url,
            duration: 0,
            timestamp,
            state: 'done'
          };
        case WL_MsgDataType.WL_MSG_DATA_LOCATION_TYPE:
          return {
            msgId: msg.msgId!,
            created: msg.created!,
            isSelf,
            name: name,
            avatar: avatar,
            type: MessageType.LOCATION,
            title: msg.locationData?.name,
            address: msg.locationData?.address,
            mapImage: msg.locationData?.mapUrl,
            timestamp,
            state: 'done'
          };
        default:
          throw new Error(`Unsupported message type: ${msg.msgType}`);
      }
    });
  },

  async loadMsgData(sessionId: Long, lastMsgId: number): Promise<Message[]> {
    // Load message data from WeilaCore
    // step1 get with weilaCore.weila_get_msgs
    let weilaCore: WeilaCore = getApp<IAppOption>().globalData.weilaCore!;

    try {
      const res = await weilaCore.weila_get_msgs({
        sessionId: sessionId,
        sessionType: WL_SessionType.SESSION_TYPE_SERVICE
      }, lastMsgId, 10);

      console.log("weila_get_msgs", res);

      if (res.msgList !== null) {
        console.log("msgDatas", res.msgList);

        let messages:Message[] = this.transformToWeChatMessages(res.msgList);

        console.log("messages", messages);
        return messages;
      }
    } catch (error) {
      console.error("Error loading message data:", error);
      return Promise.reject(error);
    }

    return [] as Message[];
  },

  onLoad(query: any) {
    // get parameters from wechat query
    let sessionId = query.sessionId;
    let lastMsgId = query.lastMsgId;

    let loginUserInfo = getApp<IAppOption>().globalData.weilaCore!.weila_get_storage_instance().getLoginUserInfo()!;

    this.setData({
      sessionId: sessionId,
      loginUserInfo: loginUserInfo,
    });

    // Set the navigation bar title
    wx.setNavigationBarTitle({
      title: '产品设计交流群'
    });
    
    // Configure navigation bar buttons
    wx.setNavigationBarColor({
      frontColor: '#000000',
      backgroundColor: '#ffffff'
    });

    console.log("sessionId and lastMsgId", sessionId, lastMsgId);
    
    this.loadMsgData(sessionId, lastMsgId).then((msgs: Message[]) => {
      this.setData({
        messages: msgs
      }, () => {
        this.calculateMessagesHeight(this.data.messages).then(() => {
          this.scrollToBottom();
        })
      })
    })
    // 设置录音回调
    this.setupRecorderListener();

    getApp<IAppOption>().globalData.eventEmitter.on("session_msg", this.onReceiveMsg.bind(this));
  },

  onReceiveMsg(msg: WL_MsgData) {
    console.log("session_msg", msg);
    
    if (Long.fromString(this.data.sessionId).equals(msg.sessionId)) {
      let newMsg = this.transformToWeChatMessages([msg]);
      this.setData({
        messages: [...this.data.messages, ...newMsg]
      }, () => {
        this.calculateMessagesHeight(this.data.messages).then(() => {
          this.scrollToBottom();
        })
      });
    }
  },

  onReady() {
    // 获取系统信息计算安全区域
    const safeArea = wx.getWindowInfo().safeArea;
    const safeAreaBottom = wx.getWindowInfo().windowHeight - safeArea.bottom;

    this.setData({
      safeAreaBottom
    });
  },

  onUnload() {
    // 清除录音计时器
    if (this.data.recordingTimer) {
      clearInterval(this.data.recordingTimer);
    }

    getApp<IAppOption>().globalData.eventEmitter.off("session_msg", this.onReceiveMsg.bind(this));
  },
  
  // 设置录音监听器
  setupRecorderListener() {
    // 录音开始事件
    recorderManager.onStart(() => {
      console.log('录音开始');
      // 开始录音计时
      const timer = setInterval(() => {
        this.setData({
          recordingTime: this.data.recordingTime + 1
        });
        
        // 限制最长录音时间为60秒
        if (this.data.recordingTime >= 60) {
          this.stopRecording();
        }
      }, 1000);
      
      this.setData({
        recordingTimer: timer,
        recordingState: 'recording'
      });
    });
    
    // 录音结束事件
    recorderManager.onStop((res) => {
      console.log('录音结束', res);
      // 录音文件地址
      const { tempFilePath, duration } = res;
      
      // 清除计时器
      if (this.data.recordingTimer) {
        clearInterval(this.data.recordingTimer);
      }
      
      // 如果不是取消状态，则发送语音消息
      if (this.data.recordingState === 'recording' && duration >= 1000) {
        // 发送语音消息
        this.sendVoiceMessage(tempFilePath, Math.round(duration / 1000));
      }
      
      // 重置录音状态
      this.setData({
        recordingState: 'idle',
        recordingTime: 0,
        recordingTimer: null
      });
    });
    
    // 录音错误事件
    recorderManager.onError((res) => {
      console.error('录音错误:', res);
      wx.showToast({
        title: '录音失败',
        icon: 'none'
      });
      
      this.setData({
        recordingState: 'idle',
        recordingTime: 0
      });
      
      if (this.data.recordingTimer) {
        clearInterval(this.data.recordingTimer);
      }
    });
  },
  
  // 开始录音
  startRecording(e: WechatMiniprogram.TouchEvent) {
    // 记录起始触摸位置
    this.setData({
      touchStartY: e.touches[0].clientY
    });
    
    // 检查录音权限
    wx.authorize({
      scope: 'scope.record',
      success: () => {
        // 开始录音
        recorderManager.start({
          duration: 60000, // 最长1分钟
          sampleRate: 16000,
          numberOfChannels: 1,
          encodeBitRate: 64000,
          format: 'mp3'
        });
      },
      fail: () => {
        wx.showModal({
          title: '提示',
          content: '需要录音权限才能发送语音消息',
          confirmText: '去设置',
          success: (res) => {
            if (res.confirm) {
              wx.openSetting();
            }
          }
        });
      }
    });
  },
  
  // 结束录音
  stopRecording() {
    // 如果录音时间少于1秒视为误触
    if (this.data.recordingState === 'recording' && this.data.recordingTime < 1) {
      wx.showToast({
        title: '说话时间太短',
        icon: 'none'
      });
    }
    
    // 如果是取消状态，不发送语音消息
    if (this.data.recordingState === 'will-cancel') {
      wx.showToast({
        title: '已取消发送',
        icon: 'none'
      });
    }
    
    // 停止录音
    recorderManager.stop();
  },
  
  // 录音过程中手指移动
  touchMoveRecord(e: WechatMiniprogram.TouchEvent) {
    const touchY = e.touches[0].clientY;
    const moveDistance = this.data.touchStartY - touchY;
    
    // 如果上滑超过50像素，进入取消状态
    if (moveDistance > 50 && this.data.recordingState === 'recording') {
      this.setData({
        recordingState: 'will-cancel'
      });
    } 
    // 如果下滑回到原位，恢复录音状态
    else if (moveDistance <= 50 && this.data.recordingState === 'will-cancel') {
      this.setData({
        recordingState: 'recording'
      });
    }
  },

  // 发送语音消息
  async sendVoiceMessage(filePath: string, duration: number) {
    let weilaCore: WeilaCore = getApp<IAppOption>().globalData.weilaCore!;

    const now = new Date();
    const hours = now.getHours();
    const minutes = now.getMinutes();
    const period = hours < 12 ? '上午' : '下午';
    const formattedHours = hours % 12 || 12;
    const formattedMinutes = minutes.toString().padStart(2, '0');
    
    const newMessage: Message = {
      msgId: 0,
      created: Math.floor(now.getTime() / 1000),
      isSelf: true,
      name: this.data.loginUserInfo.nick,
      avatar: this.data.loginUserInfo.avatar,
      type: MessageType.VOICE,
      content: filePath, // 语音文件路径
      duration: duration, // 语音时长
      timestamp: `${period} ${formattedHours}:${formattedMinutes}`,
      state: 'sending' // 发送状态
    };

    // 使用wx的上传接口上传语音文件
    let resultUrl = "";
    try {
      let token = weilaCore.weila_get_storage_instance().getLoginToken()!;
      const randomFilename = `${Math.floor(Math.random() * 100000)}.mp3`;
      const ret = await uploadFile(token, filePath, randomFilename, (progress) => {
        console.log(`上传进度: ${progress}%`);
      });
      console.log("uploadFile", ret);
      if (ret.errcode == 0) {
        resultUrl = ret.data.url;
        console.log("resultUrl", resultUrl);
      }else {
        console.error("uploadFile error", ret);
        wx.showToast({
          title: '上传语音失败',
          icon: 'none'
        });

        newMessage.state = 'failed';
        
      }

    } catch (error) {
      console.error('Error uploading voice message:', error);
      wx.showToast({
        title: '上传语音失败',
        icon: 'none'
      });
      newMessage.state = 'failed';
    }

    if (resultUrl !== "") {
      try {
        const ret = await weilaCore.weila_send_audio_session_msg({
          sessionId: Long.fromString(this.data.sessionId),
          sessionType: WL_SessionType.SESSION_TYPE_SERVICE
        }, resultUrl, false);

        console.log("weila_send_audio_session_msg", ret);
        newMessage.msgId = ret.msgId;
        newMessage.state = 'done'; // 标记消息已发送成功
      } catch (error) {
        console.error('Error sending audio message:', error);
        wx.showToast({
          title: '发送语音失败',
          icon: 'none'
        });
        newMessage.state = 'failed'; // 标记消息无效
      }
    }

    // 计算新消息的高度
    this.calculateMessageHeight(newMessage).then((height) => {
      const messages = [...this.data.messages, newMessage];
      
      this.setData({
        messages,
        lastMessageHeight: height,
        totalMessagesHeight: this.data.totalMessagesHeight + height
      }, () => {
        this.scrollToBottom();
      });
    });
  },
  
  // 判断是否显示时间戳
  shouldShowTimestamp(index: number): boolean {
    if (index === 0) return true;
    const currentMsg = this.data.messages[index];
    const prevMsg = this.data.messages[index - 1];
    
    // 将时间字符串转为日期对象，注意这里为了简化使用虚拟日期
    const currentTime = new Date(`2024-01-01 ${currentMsg.timestamp}`);
    const prevTime = new Date(`2024-01-01 ${prevMsg.timestamp}`);
    
    // 如果时间差大于5分钟，显示时间戳
    return currentTime.getTime() - prevTime.getTime() > 5 * 60 * 1000;
  },

  // 处理消息点击
  handleMessageClick(e: WechatMiniprogram.TouchEvent) {
    const item: Message = e.currentTarget.dataset.item;

    switch (item.type) {
      case MessageType.TEXT:
        console.log('点击了文本消息:', item.content);
        break;
      case MessageType.IMAGE:
        console.log('点击了图片消息:', item.content);
        wx.previewImage({
          urls: [item.content || ''],
        });
        break;
      case MessageType.VIDEO:
        console.log('点击了视频消息:', item.content);
        // 播放视频
        wx.navigateTo({
          url: `/pages/common/video-player/video-player?url=${encodeURIComponent(item.content || '')}`
        });
        break;
      case MessageType.VOICE:
        console.log('点击了语音消息:', item.duration);
        // 播放语音
        const innerAudioContext = wx.createInnerAudioContext();
        innerAudioContext.src = item.content || '';
        innerAudioContext.play();
        break;
      case MessageType.LOCATION:
        console.log('点击了位置消息:', item.address);
        // 打开位置
        wx.openLocation({
          latitude: 31.2304, // 示例纬度
          longitude: 121.4737, // 示例经度
          name: '公司地址',
          address: item.address || '',
        });
        break;
    }
  },

  // 处理输入变化
  onInputChange(e: WechatMiniprogram.Input) {
    this.setData({
      inputMessage: e.detail.value
    });
  },

  // 切换语音模式
  toggleVoiceMode() {
    this.setData({
      isVoiceMode: !this.data.isVoiceMode,
      showAttachmentMenu: false
    });
  },

  // 切换附件菜单
  toggleAttachmentMenu() {
    this.setData({
      showAttachmentMenu: !this.data.showAttachmentMenu
    });
  },

  // 处理附件选择
  handleAttachment(e: WechatMiniprogram.TouchEvent) {
    const { type } = e.currentTarget.dataset;
    
    this.setData({
      showAttachmentMenu: false
    });
    
    switch (type) {
      case MessageType.IMAGE:
        this.chooseImage();
        break;
      case MessageType.VIDEO:
        this.chooseVideo();
        break;
      case MessageType.LOCATION:
        this.chooseLocation();
        break;
      case 'file':
        wx.showToast({
          title: '小程序暂不支持发送文件',
          icon: 'none'
        });
        break;
    }
  },
  
  // 选择图片
  chooseImage() {
    console.log('选择图片');
    
    wx.chooseMedia({
      count: 1,
      mediaType: ['image'],
      success: (res) => {
        const tempFilePath = res.tempFiles[0].tempFilePath;
        console.log('选择的图片:', tempFilePath);
        
        this.sendImageMessage(tempFilePath);
      }
    });
  },
  
  // 选择视频
  chooseVideo() {
    console.log('选择视频');
    
    wx.chooseMedia({
      count: 1,
      mediaType: ['video'],
      success: (res) => {
        const tempFilePath = res.tempFiles[0].tempFilePath;
        const duration = res.tempFiles[0].duration;
        const size = res.tempFiles[0].size;
        
        // 生成视频缩略图
        const videoContext = wx.createVideoContext('temp-video');
        const canvas = wx.createOffscreenCanvas({ type: '2d', width: 300, height: 200 });
        const ctx = canvas.getContext('2d');
        
        // 这里简化处理，实际项目中应该使用视频第一帧作为缩略图
        // 由于小程序环境限制，这里使用占位图
        const thumbnailUrl = 'https://placeholder.com/300x200';
        
        // 格式化视频时长
        const minutes = Math.floor(duration / 60);
        const seconds = Math.floor(duration % 60);
        const formattedDuration = `${minutes}:${seconds.toString().padStart(2, '0')}`;
        
        this.sendVideoMessage(tempFilePath, thumbnailUrl, formattedDuration);
      }
    });
  },
  
  // 选择位置
  chooseLocation() {
    wx.chooseLocation({
      success: (res) => {
        const { name, address, latitude, longitude } = res;
        // 生成静态地图图片
        // 实际项目中应该调用地图API生成静态图片
        const mapImageUrl = `https://api.map.baidu.com/staticimage/v2?ak=YOUR_BAIDU_MAP_AK&mcode=YOUR_MCODE&center=${longitude},${latitude}&width=300&height=200&zoom=16&markers=${longitude},${latitude}`;
        this.sendLocationMessage(name, latitude, longitude, address, mapImageUrl);
      }
    });
  },
  
  // 发送图片消息
  async sendImageMessage(filePath: string) {
    const weilaCore: WeilaCore = getApp<IAppOption>().globalData.weilaCore!;
    const userInfo = weilaCore!.weila_get_storage_instance().getLoginUserInfo()!;
    
    const newMessage: Message = {
      msgId: 0,
      created: Math.floor(Date.now() / 1000),
      isSelf: true,
      name: userInfo.nick!,
      avatar: userInfo.avatar!,
      type: MessageType.IMAGE,
      content: filePath,
      timestamp: this.formatTimestamp(Math.floor(Date.now() / 1000)),
      state: 'sending' // 发送状态
    };

    let resultUrl = "";
    try {
      // 使用wx的上传接口上传图片文件
      let token = weilaCore.weila_get_storage_instance().getLoginToken()!;
      const randomFilename = `${Math.floor(Math.random() * 100000)}.jpg`;
      const ret = await uploadFile(token, filePath, randomFilename, (progress) => {
        console.log(`上传进度: ${progress}%`);
      });
      console.log("uploadFile", ret);
      if (ret.errcode == 0) {
        resultUrl = ret.data.url;
        console.log("resultUrl", resultUrl);
      }else {
        console.error("uploadFile error", ret);
        wx.showToast({
          title: '上传图片失败',
          icon: 'none'
        });

        newMessage.state = 'failed'; // 标记消息无效
      }
    }catch (error) {
      console.error('Error uploading image message:', error);
      wx.showToast({
        title: '上传图片失败',
        icon: 'none'
      });
      newMessage.state = 'failed'; // 标记消息无效
    }

    if (resultUrl !== "") {
      newMessage.content = resultUrl; // 更新消息内容为上传后的图片URL
      try {
        const ret = await weilaCore.weila_send_image_session_msg({
          sessionId: Long.fromString(this.data.sessionId),
          sessionType: WL_SessionType.SESSION_TYPE_SERVICE
        }, resultUrl, false);
        
        console.log("weila_send_image_session_msg", ret);
        newMessage.msgId = ret.msgId;
        newMessage.state = 'done'; // 标记消息已发送成功
      }catch (error) {
        console.error('Error sending image message:', error);
        wx.showToast({
          title: '发送图片失败',
          icon: 'none'
        });
        newMessage.state = 'failed'; // 标记消息无效
      }
    }

    // 计算新消息的高度
    this.calculateMessageHeight(newMessage).then((height) => {
      const messages = [...this.data.messages, newMessage];
      this.setData({
        messages,
        lastMessageHeight: height,
        totalMessagesHeight: this.data.totalMessagesHeight + height
      }, () => {
        this.scrollToBottom();
      });
    });
  },
  
  // 发送视频消息
  async sendVideoMessage(filePath: string, thumbnail: string, duration: string) {
    let weilaCore: WeilaCore = getApp<IAppOption>().globalData.weilaCore!;
    const now = new Date();
    const hours = now.getHours();
    const minutes = now.getMinutes();
    const period = hours < 12 ? '上午' : '下午';
    const formattedHours = hours % 12 || 12;
    const formattedMinutes = minutes.toString().padStart(2, '0');

    // using api to upload video file
    
    const newMessage: Message = {
      msgId: 0,
      created: Math.floor(now.getTime() / 1000),
      isSelf: true,
      name: this.data.loginUserInfo.nick,
      avatar: this.data.loginUserInfo.avatar,
      type: MessageType.VIDEO,
      content: filePath,
      thumbnail: thumbnail,
      duration: duration,
      timestamp: `${period} ${formattedHours}:${formattedMinutes}`,
      state: 'sending' // 发送状态
    };

    let resultUrl = "";
    const randomFilename = `${Math.floor(Math.random() * 100000)}.mp4`;
    try {
      const token = weilaCore.weila_get_storage_instance().getLoginToken()!;
      const ret = await uploadFile(token, filePath, randomFilename, (progress) => {
        console.log(`上传进度: ${progress}%`);
      });
      console.log("uploadFile", ret);
      if (ret.errcode == 0) {
        resultUrl = ret.data.url;
        console.log("resultUrl", resultUrl);
      }else {
        console.error("uploadFile error", ret);
        wx.showToast({
          title: '上传视频失败',
          icon: 'none'
        });

        newMessage.state = 'failed'; // 标记消息无效
      }
    }catch (error) {
      console.error('Error uploading video message:', error);
      wx.showToast({
        title: '上传视频失败',
        icon: 'none'
      });
      newMessage.state = 'failed'; // 标记消息无效
    }

    if (resultUrl !== "") {
      try {
        const ret = await weilaCore.weila_send_video_session_msg({
          sessionId: Long.fromString(this.data.sessionId),
          sessionType: WL_SessionType.SESSION_TYPE_SERVICE
        }, {
          url: resultUrl,
          thumbnail: thumbnail,
          name: randomFilename,
          size: parseInt(duration),
        } as WL_MediaData, false);

        console.log("weila_send_video_session_msg", ret);
        newMessage.msgId = ret.msgId;
        newMessage.state = 'done'; // 标记消息有效

      }catch (error) {
        console.error('Error sending video message:', error);
        wx.showToast({
          title: '发送视频失败',
          icon: 'none'
        });
        newMessage.state = 'failed'; // 标记消息无效
      }
    }

    // 计算新消息的高度
    this.calculateMessageHeight(newMessage).then((height) => {
      const messages = [...this.data.messages, newMessage];
      this.setData({
        messages,
        lastMessageHeight: height,
        totalMessagesHeight: this.data.totalMessagesHeight + height
      }, () => {
        this.scrollToBottom();
      });
    });
  },
  
  // 发送位置消息
  async sendLocationMessage(title: string, 
    latitude: number, longitude: number,
    address: string, mapImage: string) {
    let weilaCore: WeilaCore = getApp<IAppOption>().globalData.weilaCore!;
    const now = new Date();
    const hours = now.getHours();
    const minutes = now.getMinutes();
    const period = hours < 12 ? '上午' : '下午';
    const formattedHours = hours % 12 || 12;
    const formattedMinutes = minutes.toString().padStart(2, '0');
    
    const newMessage: Message = {
      msgId: 0,
      isSelf: true,
      name: this.data.loginUserInfo.nick,
      avatar: this.data.loginUserInfo.avatar,
      type: MessageType.LOCATION,
      title: title,
      latitude: latitude,
      longitude: longitude,
      address: address,
      mapImage: mapImage,
      created: Math.floor(now.getTime() / 1000),
      timestamp: `${period} ${formattedHours}:${formattedMinutes}`,
      state: 'sending' // 发送状态
    };
    
    try {
      const ret = await weilaCore.weila_send_share_location_session_msg({
        sessionId: Long.fromString(this.data.sessionId),
        sessionType: WL_SessionType.SESSION_TYPE_SERVICE
      }, {
        latitude,
        longitude,
        type: "gcj02",
        name: title,
        address: address,
        mapUrl: mapImage,
      } as WL_LocationData, false);

      newMessage.msgId = ret.msgId;
      newMessage.state = 'done';
    }catch (e) {
      console.error('Error sending location message:', e);
      wx.showToast({
        title: '发送位置失败',
        icon: 'none'
      });

      newMessage.state = 'failed'; // 标记消息无效
    }

    // 计算新消息的高度
    this.calculateMessageHeight(newMessage).then((height) => {
      const messages = [...this.data.messages, newMessage];
      this.setData({
        messages,
        lastMessageHeight: height,
        totalMessagesHeight: this.data.totalMessagesHeight + height
      }, () => {
        this.scrollToBottom();
      });
    });
  },

  // 发送消息
  async sendMessage() {
    let weilaCore: WeilaCore = getApp<IAppOption>().globalData.weilaCore!;
    if (!this.data.inputMessage.trim()) return;
    
    const now = new Date();
    const hours = now.getHours();
    const minutes = now.getMinutes();
    const period = hours < 12 ? '上午' : '下午';
    const formattedHours = hours % 12 || 12;
    const formattedMinutes = minutes.toString().padStart(2, '0');
    
    const newMessage: Message = {
      msgId: 0,
      created: Math.floor(now.getTime() / 1000),
      isSelf: true,
      name: this.data.loginUserInfo.nick,
      avatar: this.data.loginUserInfo.avatar,
      type: MessageType.TEXT,
      content: this.data.inputMessage,
      timestamp: `${period} ${formattedHours}:${formattedMinutes}`,
      state: 'sending' // 发送状态
    };
  

    try {
      console.log("sessionid ", this.data.sessionId);
      
      const ret = await weilaCore.weila_send_text_session_msg({
        sessionId: Long.fromString(this.data.sessionId),
        sessionType: WL_SessionType.SESSION_TYPE_SERVICE,
      }, newMessage.content!, false);

      console.log("weila_send_text_session_msg", ret);

      newMessage.msgId = ret.msgId;
      newMessage.state = 'done'; // 标记消息已发送成功

      this.setData({
        inputMessage: ''
      });
    }catch (e) {
      console.error('Error sending message:', e);
      wx.showToast({
        title: '发送消息失败',
        icon: 'none'
      });

      newMessage.state = 'failed'; // 标记消息无效
    }

    // 计算新消息的高度
    this.calculateMessageHeight(newMessage).then((height) => {
      const messages = [...this.data.messages, newMessage];
      this.setData({
        messages,
        lastMessageHeight: height,
        totalMessagesHeight: this.data.totalMessagesHeight + height
      }, () => {
        this.scrollToBottom();
      });
    });
  },
  
  // 处理下拉刷新
  onPullDownRefresh() {
    // 记录当前滚动位置
    const query = wx.createSelectorQuery();
    query.select('#chatContainer').scrollOffset((res) => {
      this.setData({
        previousScrollPosition: res.scrollTop,
        isRefreshing: true
      });
    }).exec();

    let lastMsgId = this.data.messages.length > 0 ? this.data.messages[0].msgId : 0;
    console.log("lastMsgId", lastMsgId);

    // 加载历史消息
    this.loadMsgData(Long.fromString(this.data.sessionId), lastMsgId).then(async (msgs: Message[]) => {
      const newMsgsHeight = await this.calculateMessagesHeight(msgs);
      const updatedMessages = msgs.concat(this.data.messages);
      this.setData({
      messages: updatedMessages,
      totalMessagesHeight: this.data.totalMessagesHeight + newMsgsHeight,
      isRefreshing: false
      }, () => {
      this.setData({
        scrollTop: newMsgsHeight + this.data.previousScrollPosition
      });
      });
    });
  },
  
  // 处理滚动事件
  handleScroll(e: WechatMiniprogram.ScrollViewScroll) {
    const { scrollTop, scrollHeight } = e.detail;
    const clientHeight = wx.getWindowInfo().windowHeight - this.data.safeAreaBottom;
    
    // 判断是否滚动到底部
    const isBottom = scrollTop + clientHeight >= scrollHeight - 30;
    
    if (this.data.isAtBottom !== isBottom) {
      this.setData({
        isAtBottom: isBottom
      });
    }
    
    // 保存滚动位置，用于下拉刷新后恢复
    this.data.previousScrollPosition = scrollTop;
  },
  
  // 滚动到底部
  scrollToBottom() {
    wx.createSelectorQuery()
      .select('#chatContainer')
      .boundingClientRect((rect) => {
        if (!rect) return;

        const threshold = 10;

        if (this.data.scrollTop + rect.height < this.data.totalMessagesHeight - threshold) {
          this.setData({
            scrollTop: this.data.totalMessagesHeight - rect.height
          });
        }
      })
      .exec();
  },
  
  // 计算所有消息的总高度
  calculateMessagesHeight(messages: Message[]): Promise<number> {
    return Promise.all(messages.map(msg => this.calculateMessageHeight(msg)))
      .then((heights) => {
        const totalHeight = heights.reduce((sum, height) => sum + height, 0);
        
        this.setData({
          totalMessagesHeight: totalHeight
        });

        return totalHeight;
      });
  },
  
  // 计算单个消息的高度
  calculateMessageHeight(message: Message): Promise<number> {
    return new Promise((resolve) => {
      // Base height includes avatar, name, padding
      const baseHeight = 60;
      
      switch (message.type) {
        case MessageType.TEXT:
          // Text message height calculation remains similar but more precise
          resolve(this.heightForTextMessage(message.content || ''));
          break;
          
        case MessageType.IMAGE:
          // Get actual image dimensions
          if (message.content) {
            wx.getImageInfo({
              src: message.content,
              success: (res) => {
                // Calculate aspect ratio and determine displayed height
                const maxWidth = 240; // Maximum width of message bubble
                const aspectRatio = res.width / res.height;
                let imageHeight = Math.min(240, res.height);
                
                // Maintain aspect ratio
                if (res.width > maxWidth) {
                  imageHeight = maxWidth / aspectRatio;
                }
                
                // Add padding and base elements
                resolve(baseHeight + imageHeight + 16);
              },
              fail: () => {
                // Fallback if image info can't be retrieved
                resolve(baseHeight + 150);
              }
            });
          } else {
            resolve(baseHeight + 150); // Fallback height
          }
          break;
          
        case MessageType.VIDEO:
          // Similar approach for video thumbnails
          if (message.thumbnail) {
            wx.getImageInfo({
              src: message.thumbnail,
              success: (res) => {
                const maxWidth = 240;
                const aspectRatio = res.width / res.height;
                let thumbnailHeight = Math.min(180, res.height);
                
                if (res.width > maxWidth) {
                  thumbnailHeight = maxWidth / aspectRatio;
                }
                
                // Add height for play button and duration indicator
                resolve(baseHeight + thumbnailHeight + 24);
              },
              fail: () => {
                resolve(baseHeight + 180);
              }
            });
          } else {
            resolve(baseHeight + 180);
          }
          break;
          
        case MessageType.VOICE:
          // Voice message height is relatively fixed
          resolve(baseHeight + 40);
          break;
          
        case MessageType.LOCATION:
          // Location messages have fixed height map preview
          resolve(baseHeight + 140);
          break;
          
        default:
          resolve(baseHeight + 60);
      }
    });
  },
  
  // Improved text height calculation
  heightForTextMessage(text: string): number {
    // Base height (avatar + name)
    const baseHeight = 60;
    
    // Calculate based on character count and line breaks
    const fontSize = 16; // font size in px
    const lineHeight = 1.5; // line height multiplier
    const maxWidth = 240; // max message width in px
    const charsPerLine = Math.floor(maxWidth / (fontSize * 0.6)); // approximate chars per line
    
    // Count actual lines (including hard line breaks)
    const lines = text.split('\n');
    let totalLines = 0;
    
    lines.forEach(line => {
      totalLines += Math.max(1, Math.ceil(line.length / charsPerLine));
    });
    
    // Calculate text block height
    const textHeight = totalLines * fontSize * lineHeight;
    
    // Add padding and margins
    return baseHeight + textHeight + 24;
  },
  
  // 返回上一页
  onBack() {
    wx.navigateBack();
  },
  
  // 显示群聊选项
  showOptions() {
    wx.showActionSheet({
      itemList: ['群聊信息', '消息管理', '设置提醒', '退出群聊'],
      success: (res) => {
        console.log('选择了选项:', res.tapIndex);
      }
    });
  }
});